﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpCmd.IO;

namespace SharpCmd.Controls.FileSystemViewers
{
	internal abstract class FileSystemViewer : UserControl, IFileSystemViewer
	{
		/// <summary>
		/// The control that displays filesystem - listview, tree
		/// </summary>
		protected Control ViewControl { get; set; }

		protected string path;

		public FileSystemViewer ()
		{
		}

		protected IEnumerable<FSObjectInfo> GetFSInfos ()
		{
			DirectoryInfo di = new DirectoryInfo (Path);
			try {
				var dirs = di.GetDirectories ().OrderBy (p => p.Name).Select (p => FSObjectInfo.FromDirectoryInfo (p));
				var files = di.GetFiles ().OrderBy (p => p.Name).Select (p => FSObjectInfo.FromFileInfo (p));
				if (di.Parent != null)
					return GetParentInfo (di).Concat (dirs).Concat (files);
				else
					return dirs.Concat (files);
			} catch (UnauthorizedAccessException ex) {
				return GetParentInfo (di);
			}
		}
		
		private FSObjectInfo[] GetParentInfo (DirectoryInfo di)
		{
			return new FSObjectInfo[] 
                {
                    new FSObjectInfo () 
                    {
                        FullName = di.Parent.FullName,
                        Size = FSObjectInfo.DirectoryInitialSize,
                        LastWriteTime = di.Parent.LastWriteTime, 
                        Type = FSObjectType.Directory,
                        Name = "..",
                        Fake = true,
                        AlwaysOnTop = true
                    } 
                };
		}

		public virtual string Path { get; set; }

		public string GetHeader ()
		{
			DirectoryInfo di = new DirectoryInfo (Path);
			return di.Name;
		}

		public abstract event Util.DriveChangedDelegate DriveChanged;
		public abstract event Util.PathChangedDelegate PathChanged;
		public delegate void SelectedIndexChangedHandler (int totalFileCount,int totalDirectoryCount,int selectedFileCount,int selectedDirectoryCount,long totalSize,long selectedSize);

		public abstract event SelectedIndexChangedHandler SelectedIndexChanged;

		/// <summary>
		/// Gets first selected item OR a focused item
		/// </summary>
		public abstract FSObjectInfo SelectedItem { get; }

		/// <summary>
		/// Returns if this viewer has a selected item
		/// </summary>
		public abstract bool HasSelectedItem { get; }

		public abstract FSObjectInfo FocusedItem { get; }

		/// <summary>
		/// Gets a list of selected items or a single focused item
		/// </summary>
		public abstract List<FSObjectInfo> SelectedItemInfos { get; }

		public abstract void Reload ();

		public abstract void OnDriveChanged (string drive);

		public virtual void DoFocus ()
		{
			ViewControl.Focus ();
		}

		public abstract void FocusItemWithPath (string path);

		/// <summary>
		/// Go one directory up
		/// </summary>
		public virtual void GoToParentDirectory ()
		{
			DirectoryInfo di = new DirectoryInfo (Path);
			if (di.Parent == null)
				return;
			string oldPath = Path;
			Path = di.Parent.FullName;
		}

		/// <summary>
		/// Go to the root directory
		/// </summary>
		public void GoToRootDirectory ()
		{
			DirectoryInfo di = new DirectoryInfo (Path);
			Path = di.Root.FullName;
		}

		public virtual void Sort (SortType sortType)
		{
			throw new NotImplementedException ();
		}

        #region selection
		public abstract void InvertSelection ();

		public abstract void SelectAll ();

		public abstract void Select (string group);

		public abstract void UnSelect (string group);

		/// <summary>
		/// Selects all items with same extension as focused item
		/// </summary>
		public abstract void SelectSameExtension ();
        #endregion
	}
}